
NAMESPACE_BEGIN(interp)

    template <class EncodingT>
    String<EncodingT>::String()
    {
        setValue(EncodingT::EMPTY);
    }

    template <class EncodingT>
    String<EncodingT>::String(typename EncodingT::string_t const& value)
    {
        setValue(value);
    }

    template <class EncodingT>
    String<EncodingT>::String(typename EncodingT::char_t const& value)
    {
        setValue(typename EncodingT::string_t(value));
    }

    template <class EncodingT>
    String<EncodingT>::String(shared_ptr< Base<EncodingT> > const& value)
    {
        typename EncodingT::string_t str;     
        if (check_string(value, str))
        {
            setValue(str);
        }
    }

    template <class EncodingT>
    String<EncodingT>::~String()
    {}

    template <class EncodingT>
    typename EncodingT::string_t const& String<EncodingT>::getValue() const
    {
        return m_value;
    }
	
    template <class EncodingT>
    void String<EncodingT>::setValue(typename EncodingT::string_t const& value)
    {
        m_value = value;
    }

    template <class EncodingT>
    typename EncodingT::string_t String<EncodingT>::toString() const
    {
        return getValue();
    }

    template <class EncodingT>
    shared_ptr< Base<EncodingT> > String<EncodingT>::clone() const
    {
        return shared_ptr< Base<EncodingT> >(new String<EncodingT>(getValue()));
    }

    template <class EncodingT>
    typename EncodingT::string_t String<EncodingT>::getClassName() const
    {
        return C("String");
    }

    template <class EncodingT>
    shared_ptr< Base<EncodingT> > String<EncodingT>::invoke(const typename EncodingT::string_t& method, std::vector< shared_ptr< Base<EncodingT> > >& params)
    {
        shared_ptr< Base<EncodingT> > obj(new Base<EncodingT>());
        
        ParameterArray args, ret;
        if (check_parameters_array(params, args))
        {
            if (tryInvoke(this, C("String"), method, args, ret))
            {
                find_parameter(ret, FACTORY_RETURN_PARAMETER, obj);
                for (size_t i = 0; i < params.size(); ++i)
                {
                    find_parameter(ret, i, params[i]);
                }
            }
            else
            {
                Category * logger = &Category::getInstance(LOGNAME);
                logger->errorStream() << "Unexpected call in String, no method \"" << A(method) << "\" exists.";
            }
        }
        return obj;
    }

    template <class EncodingT>
    shared_ptr< Base<EncodingT> > String<EncodingT>::concat(shared_ptr< Base<EncodingT> > const& val) const
    {
        shared_ptr< Base<EncodingT> > res(new String<EncodingT>);
        typename EncodingT::string_t str;     
        if (check_string(val, str))
        {
            res.reset(new String<EncodingT>(getValue() + str));
        }
        return res;
    }

    template <class EncodingT>
    shared_ptr< Base<EncodingT> > String<EncodingT>::equals(shared_ptr< Base<EncodingT> > const& val) const
    {
        shared_ptr< Base<EncodingT> > res(new Bool<EncodingT>);
        typename EncodingT::string_t str;     
        if (check_string(val, str))
        {
            res.reset(new Bool<EncodingT>(boost::iequals(getValue(), str)));
        }
        return res;
    }

    template <class EncodingT>
    shared_ptr< Base<EncodingT> > String<EncodingT>::notEquals(shared_ptr< Base<EncodingT> > const& val) const
    {
        shared_ptr< Base<EncodingT> > res(new Bool<EncodingT>);
        typename EncodingT::string_t str;     
        if (check_string(val, str))
        {
            res.reset(new Bool<EncodingT>(!boost::iequals(getValue(), str)));
        }
        return res;
    }

    template <class EncodingT>
    bool check_string(shared_ptr< Base<EncodingT> > const& val, typename EncodingT::string_t& n)
    {
        n = val->toString();
        return true;
    }

    template <class EncodingT>
    bool check_char(shared_ptr< Base<EncodingT> > const& val, typename EncodingT::char_t& n)
    {
        typename EncodingT::string_t tmp = val->toString();
        if (tmp.size() > 0)
        {
            n = tmp[0];
        }
        return tmp.size() > 0;
    }

NAMESPACE_END

